#ifndef __PTR_H__
#define __PTR_H__

class PtrClass
{
public:
	PtrClass():m_ref(0)
	{}
	PtrClass(const PtrClass& other)
	{m_ref=other.m_ref;}
	virtual ~PtrClass(){}
	void retain() {m_ref++;}
	void release() {m_ref--;if(m_ref<=0) delete this;}
private:
	int m_ref;
};

template<class T>
class Ptr
{
public:
	Ptr()
	{
		m_ptr=0;
	}
	Ptr(const Ptr<T>& other)
	{
		m_ptr=other.m_ptr;
		if(m_ptr)
			m_ptr->retain();
	}
	Ptr(T* t)
	{
		m_ptr=t;
		if(m_ptr)
			m_ptr->retain();
	}
	~Ptr()
	{
		if(m_ptr)
			m_ptr->release();
	}
	T& operator*() {return *m_ptr;}
	T* operator->() {return m_ptr;}
	template<class M>
	Ptr& operator=(Ptr<M>& other) 
	{
		if(m_ptr)
			m_ptr->release();
		m_ptr=dynamic_cast<M*>(other->ptr);
		if(m_ptr)
			m_ptr->retain();
		return *this;
	}
	Ptr& operator=(T* other) 
	{
		if(m_ptr)
			m_ptr->release();
		m_ptr=other;
		if(m_ptr)
			m_ptr->retain();
		return *this;
	}
	template<class M>
	Ptr<M> Cast()
	{
		if(!m_ptr)
			return 0;
		return Ptr<M>((M*)(m_ptr));
	}
	bool operator==(T* ptr) {return m_ptr==ptr;}
	bool operator!=(T* ptr) {return m_ptr!=ptr;}

private:
	T* m_ptr;
};

#endif

